package com.jingbian.cppccbackend.service.impl.user;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.jingbian.cppccbackend.entity.*;
import com.jingbian.cppccbackend.entity.dto.PublicProposalsDTO;
import com.jingbian.cppccbackend.entity.dto.SearchProposalDTO;
import com.jingbian.cppccbackend.entity.dto.SubmitProposalsDTO;
import com.jingbian.cppccbackend.mapper.user.ProposalAttachmentsMapper;
import com.jingbian.cppccbackend.mapper.user.ProposalSignersMapper;
import com.jingbian.cppccbackend.mapper.user.ProposalsMapper;
import com.jingbian.cppccbackend.mapper.user.UsersMapper;
import com.jingbian.cppccbackend.service.user.ProposalsService;
import com.jingbian.cppccbackend.utils.ThreadLocalUtil;
import com.jingbian.cppccbackend.vo.PageVO;
import com.jingbian.cppccbackend.vo.ProposalsDetailVO;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRPr;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 提案信息表 服务实现类
 * </p>
 *
 * @author yezi
 * @since 2025-02-11
 */
@Service
public class ProposalsServiceImpl extends ServiceImpl<ProposalsMapper, Proposals> implements ProposalsService {

    @Autowired
    private ProposalsMapper proposalsMapper;
    @Autowired
    private UsersMapper usersMapper;
    @Autowired
    private ProposalSignersMapper proposalSignersMapper;
    @Autowired
    private ProposalAttachmentsMapper proposalAttachmentsMapper;

    @Override
    public PageInfo<Proposals> getProposalsByUserId(SearchProposalDTO searchProposalDTO) {
        // 开启分页
        PageHelper.startPage(searchProposalDTO.getPageNum(), searchProposalDTO.getPageSize());
        Map<String, Object> claims = ThreadLocalUtil.get();
        searchProposalDTO.setUserId((Integer)claims.get("uid"));
        List<Proposals> list = proposalsMapper.getProposalsByUserId(searchProposalDTO);
        return new PageInfo<>(list);
    }

    @Override
    public List<Proposals> getPublicProposals() {
        return proposalsMapper.getPublicProposals();
    }

    //获取提案详情
    @Override
    public Proposals getProposalById(Integer proposalId) {
        return proposalsMapper.getProposalById(proposalId);
    }

    //【管理员】获取提案数据
    @Override
    public PageVO<Proposals> getAllProposalsWithDetails(
            Integer pageNum,
            Integer pageSize,
            String status,
            String proposalType,
            String startDate,
            String endDate,
            String sort,
            Integer pageStatus
    ) {
        PageVO<Proposals> pb = new PageVO<>();
        PageHelper.startPage(pageNum, pageSize);
        List<Proposals> proposals = proposalsMapper.getAllProposalsWithDetails(
                status, proposalType, startDate, endDate, sort,pageStatus);
        Page<Proposals> pag = (Page<Proposals>) proposals;
        pb.setTotal(pag.getTotal());
        pb.setItems(pag.getResult());
        return pb;
    }

    //【管理员】更新提案数据状态
    @Override
    public void updateProposalStatus(Integer proposalId, String status,Boolean isOr,Integer pageStatus) {
        proposalsMapper.updateProposalStatus(proposalId, status,isOr,pageStatus);
    }

    //【管理员】搜索框查找
    @Override
    public List<Proposals> searchProposals(String searchText) {
        if (StringUtils.isEmpty(searchText)) {
            return proposalsMapper.selectList(null);
        }
        return proposalsMapper.searchProposals(searchText);
    }

    @Override
    public Integer applyCancelProposal(Integer proposalId) {
        /**
         * 返回1，则表示提案不存在
         * 返回2，则表示与用户id不一致
         * 返回3，申请取消提案成功！
         * 返回4，提案未过初审
         * 返回5，提案正在进行取消操作！
         */
        QueryWrapper<Proposals> wrapper = new QueryWrapper<>();
        wrapper.eq("pid",proposalId);
        Proposals proposals = proposalsMapper.selectOne(wrapper);
        if(proposals == null) {
            return 1;
        }
        Map<String, Object> claims = ThreadLocalUtil.get();
        Integer uid = (Integer)claims.get("uid");
        if (!proposals.getUserId().equals(uid)){
            return 2;
        }
        if (proposals.getIsCancel()){
            return 5;
        }
        if (Objects.isNull(proposals.getIsOr())||!proposals.getIsOr()){
            return 4;
        }
        UpdateWrapper<Proposals> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("pid",proposalId).eq("user_id",uid).set("is_cancel",true);
        proposalsMapper.update(proposals, updateWrapper);
        return 3;
    }

    @Override
    public PageInfo<Proposals> getSearchPublic(PublicProposalsDTO publicProposalsDTO) {
        PageHelper.startPage(publicProposalsDTO.getPageNum(), publicProposalsDTO.getPageSize());
        List<Proposals> list = proposalsMapper.getSearchPublicProposal(publicProposalsDTO);
        return new PageInfo<>(list);
    }

    @Override
    @Transactional
    public ProposalsDetailVO getDetailById(Integer proposalId) {
        Proposals proposals = proposalsMapper.getProposalById(proposalId);
        ProposalsDetailVO proposalsDetailVO = new ProposalsDetailVO();
        BeanUtils.copyProperties(proposals, proposalsDetailVO);
        // 2. 解析签收人ID列表
        if(proposals.getSigners() != null) {
            List<Integer> signerIds = Arrays.stream(proposals.getSigners().split(","))
                    .map(Integer::parseInt)
                    .collect(Collectors.toList());
            // 3. 批量查询用户名
            List<Users> users = usersMapper.selectUsersByIds(signerIds);
            // 4. 提取用户名并设置到提案对象
            List<String> names = users.stream()
                    .map(Users::getUname)
                    .collect(Collectors.toList());
            proposalsDetailVO.setSignersName(names);
        }
        // 5.批量查询提案的附件并获取其附件名字
        LambdaQueryWrapper<ProposalAttachments> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper
                .eq(ProposalAttachments::getProposalId,proposalId);
        // 2. 查询数据库，获取 ProposalAttachments 列表
        List<ProposalAttachments> attachments = proposalAttachmentsMapper.selectList(lambdaQueryWrapper);
        System.out.println(attachments);
        // 3. 转换为 FileInfo 列表
        List<FileInfo> fileInfos = attachments.stream()
                .filter(att -> att.getFileName() != null && att.getFilePath() != null) // 过滤无效数据
                .map(att -> {
                    String fileName = "";
                    if(att.getIsHandle()){
                        fileName = "专项--"+att.getFileName();
                    }else{
                        fileName = "提案--"+att.getFileName();
                    }
                    String fileUrl = att.getFilePath(); // 根据路径生成访问 URL
                    String fileSize = att.getSize(); // 计算文件大小（需实现）
                    return new FileInfo(fileName, fileUrl, fileSize);
                })
                .collect(Collectors.toList());
        // 4. 设置到 VO 对象
        System.out.println(fileInfos);
        proposalsDetailVO.setFileInfo(fileInfos);
        return proposalsDetailVO;
    }

    @Override
    @Transactional
    public void submitProposals(SubmitProposalsDTO proposalsDTO) {
        Map<String, Object> claims = ThreadLocalUtil.get();
        Integer uid = (Integer) claims.get("uid");

        Users users = usersMapper.selectById(uid);
        List<Integer> signerUserIds = proposalsDTO.getSignersId();

        System.out.println(proposalsDTO);
        // 1.针对提案表
        Proposals proposals = new Proposals();
        BeanUtils.copyProperties(proposalsDTO, proposals);
        proposals.setStatus("处理中");
        proposals.setSubmitTime(LocalDateTime.now());
        proposals.setUserId(uid);
        proposals.setProposer(users.getUname());
        proposals.setProposerRegion(users.getRegion());

        // 2025/4/26 进行新增
        proposals.setTopic(proposalsDTO.getTopic());
        proposals.setOrganizerWill(proposalsDTO.getOrganizerWill());
        //止步
        if(signerUserIds.isEmpty()){
            proposals.setIsOr(true); // 联名通过
            proposals.setIsOrTime(LocalDateTime.now());//直接进入
        }
        proposalsMapper.insert(proposals);

        Users userSigner = new Users();
        // 2.针对联名人表
        if (signerUserIds != null && !signerUserIds.isEmpty()) {
            List<ProposalSigners> signersList = new ArrayList<>();
            for (Integer userId : signerUserIds) {
                if(userId.equals(uid)){
                    throw new RuntimeException("不能将自己添加为联名人");
                }
                //新增
                userSigner = usersMapper.selectById(userId);
                if (userSigner == null) {
                    throw new RuntimeException("查无id为"+userId+"联名人");
                }
                if (!userSigner.getIsActive()){
                    throw new RuntimeException("查无id为"+userId+"联名人");
                }

                ProposalSigners signer = new ProposalSigners();
                signer.setProposalId(proposals.getPid()); // 设置提案ID
                signer.setUserId(userId);         // 设置联名人用户ID
                signer.setDisposeStatus("未处理"); // 初始状态（根据业务需求调整）
                signersList.add(signer);
            }
            // 批量插入（需 Mapper 支持）
            try {
                proposalSignersMapper.batchInsert(signersList);
            } catch (Exception e) {
                throw new RuntimeException("查无此联名人");
            }
        }

        // 3. 插入附件表
        List<FileInfo> filePaths = proposalsDTO.getFilePath();
        if (filePaths != null && !filePaths.isEmpty()) {
            List<ProposalAttachments> attachmentsList = new ArrayList<>();
            LocalDateTime now = LocalDateTime.now();
            for (FileInfo filePath : filePaths) {
                ProposalAttachments attachment = new ProposalAttachments();
                attachment.setProposalId(proposals.getPid());
                attachment.setFilePath(filePath.getUrl());
                attachment.setFileName(filePath.getName());
                attachment.setSize(filePath.getSize());
                attachment.setUploadTime(now); // 统一上传时间
                attachmentsList.add(attachment);
            }
            // 批量插入
            proposalAttachmentsMapper.batchInsert(attachmentsList);
        }
    }
    @Override
    public ByteArrayResource generateProposalDoc(Map<String, String> data) {
        ClassPathResource template = new ClassPathResource("word/proposalWordFrame.docx");
        XWPFDocument doc = null;
        ByteArrayOutputStream out = null;

        try {
            doc = new XWPFDocument(template.getInputStream());

            // 处理所有段落中的占位符
            for (XWPFParagraph paragraph : doc.getParagraphs()) {
                replaceParagraph(paragraph, data);
            }

            // 处理表格中的占位符
            for (XWPFTable table : doc.getTables()) {
                for (XWPFTableRow row : table.getRows()) {
                    for (XWPFTableCell cell : row.getTableCells()) {
                        for (XWPFParagraph paragraph : cell.getParagraphs()) {
                            replaceParagraph(paragraph, data);
                        }
                    }
                }
            }

            out = new ByteArrayOutputStream();
            doc.write(out);
            return new ByteArrayResource(out.toByteArray());
        } catch (IOException e) {
            throw new RuntimeException("文档生成失败", e);
        } finally {
            try {
                if (doc != null) doc.close();
                if (out != null) out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private void replaceParagraph(XWPFParagraph paragraph, Map<String, String> data) {
        String text = paragraph.getText();
        boolean containsPlaceholder = false;

        // 检查是否包含占位符
        for (String key : data.keySet()) {
            if (text.contains("{{" + key + "}}")) {
                containsPlaceholder = true;
                break;
            }
        }

        if (!containsPlaceholder) {
            return;
        }

        // 在修改之前保存样式信息
        XWPFRun firstRun = paragraph.getRuns().isEmpty() ? null : paragraph.getRuns().get(0);
        CTRPr styleRpr = firstRun != null ? firstRun.getCTR().getRPr() : null;

        // 替换所有占位符
        for (Map.Entry<String, String> entry : data.entrySet()) {
            text = text.replace("{{" + entry.getKey() + "}}",
                    entry.getValue() != null ? entry.getValue() : "");
        }

        // 清除所有runs
        for (int i = paragraph.getRuns().size() - 1; i >= 0; i--) {
            paragraph.removeRun(i);
        }

        // 创建新的run并应用样式
        XWPFRun newRun = paragraph.createRun();
        // 设置文本
        newRun.setText(text);
    }
}